package com.ruoyi.system.service.impl;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.thread.ThreadUtil;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.JsonUtils;
import com.ruoyi.system.dto.OfficialAccountsAuthDto;
import com.ruoyi.system.service.IWechatService;
import com.ruoyi.system.weixin.api.WeiXinApi;
import com.ruoyi.system.weixin.model.WxResultBody;
import com.ruoyi.system.weixin.okhttp.MyCookieStore;
import com.ruoyi.system.weixin.utils.HttpUtils;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Cookie;
import okhttp3.HttpUrl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import java.util.stream.Collectors;

/**
 * 使用redis存储token
 *
 * @author woo
 * @date 2021/8/5
 */
@Service
@Slf4j
public class WechatServiceImpl implements IWechatService {
	private static final String REDIS_KEY = "weixin-token";
	@Autowired
	private RedisCache redisCache;
	@Autowired
	private IWechatService wechatService;
	private static FutureTask<Integer> futureTask;

	@Override
	public byte[] getLoginQrCode() {
		// 1. POST请求开始登录接口，初始化cookie
		String sessionid = "" + System.currentTimeMillis() + (int) (Math.random() * 100);
		WxResultBody wxResultBody = WeiXinApi.startLogin(sessionid);
		try (InputStream inputStream = WeiXinApi.getQRCode()) {
			this.askQrCode();
			return IoUtil.readBytes(inputStream);
		} catch (IOException e) {
			throw new CustomException("获取公众号验证码失败:" + e.getMessage(), e);
		}
	}

	@Override
	public OfficialAccountsAuthDto getToken() {
		String data = redisCache.getCacheObject(REDIS_KEY);
		return JsonUtils.parseObject(data, OfficialAccountsAuthDto.class);
	}

	@Override
	public void saveToken(OfficialAccountsAuthDto dto) {
		redisCache.setCacheObject(REDIS_KEY, JsonUtils.toJsonString(dto));
	}

	@Override
	public void askQrCode() {
		if (futureTask != null) {
			//先强制终止之前的
			futureTask.cancel(true);
		}
		futureTask = new FutureTask<>(new Callable<Integer>() {
			@Override
			public Integer call() throws Exception {
				int time = 0;
				while (true) {
					time++;
					WxResultBody askQRCode = WeiXinApi.askQRCode();
					Integer status = askQRCode.getStatus();
					if (status == 3) {
						log.debug("二维码已过期");
					} else if (status == 4) {
						log.debug("已扫码，等待确认");
					} else if (status == 1) {
						log.debug("已确认登录，请稍后...");
						//说明扫码确认成功，否则重新获取图片
						// 4.确认登录后，请求登录接口，拿到登录状态的cookie
						WxResultBody bizlogin = WeiXinApi.bizlogin();
						//重定向地址
						String redirect_url = bizlogin.getRedirect_url();
						//解析成键值对
						Map<String, String> loginRes = HttpUtils.parseQueryParams(redirect_url);
						//得到token
						String token = loginRes.get("token");
						//设置全局token值
						MyCookieStore.setToken(token);
						List<Cookie> cookies = HttpUtils.client.cookieJar().loadForRequest(HttpUrl.parse("https://mp.weixin.qq.com/cgi-bin/appmsg").newBuilder().build());
						String cookieStr = cookies.stream().map(cookie -> cookie.name() + "=" + cookie.value()).collect(Collectors.joining("; "));
						OfficialAccountsAuthDto dto = new OfficialAccountsAuthDto();
						dto.setToken(token);
						dto.setCookie(cookieStr);
						wechatService.saveToken(dto);
						return 1;
					}
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					if (time == 300) {
						log.debug("超出次数,未扫描二维码,退出检测");
						break;
					}
				}
				return 0;
			}
		});
		ThreadUtil.execAsync(futureTask);
	}
}
